package com.bwstudio.demo.consumer.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.bwstudio.demo.consumer.client.EchoClient;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
public class EchoServiceImpl implements EchoService {

	@Autowired
	EchoClient echoClient;
	
//	@Autowired
//	private LoadBalancerClient loadBalancerClient;
	
	@Autowired
	private RestTemplate restTemplate;

	@Value("${spring.application.name}")
	private String appName;
	
	@SentinelResource(value = "EchoService.echoAppNameByFeign", 
			blockHandler = "echoAppNameByFeignBlockHandler", 
			fallback = "echoAppNameByFeignFallback")
	public String echoAppNameByFeign() {
		return echoClient.echo(appName);
	}

	// Block 异常处理函数，参数最后多一个 BlockException，其余与原函数一致.
	public String echoAppNameByFeignBlockHandler(BlockException ex) {
		log.warn("Oops: " + ex.getClass().getCanonicalName());
		return "EchoService.echoAppNameByFeign: 我被限流了";
	}

	// Fallback 函数，函数签名与原函数一致或加一个 Throwable 类型的参数.
	public String echoAppNameByFeignFallback(Throwable ex) {
		log.error("Oops：" + ex.getClass().getCanonicalName());
		return "EchoService.echoAppNameByFeign: 我被降级了";
	}

	
	
	/**
	 * 发现用resttemplate请求的fallback规则只能在服务消费端配置，服务提供方的限流熔断等规则无法触发
	 * 
	 */
	@SentinelResource(value = "EchoService.echoAppNameByRestTemplate", 
			blockHandler = "echoAppNameByRestTemplateBlockHandler", 
			fallback = "echoAppNameByRestTemplateFallback")
	public String echoAppNameByRestTemplate() {
		// 使用 LoadBalanceClient 和 RestTemplate 结合的方式来访问
		/*
		 * ServiceInstance serviceInstance =
		 * loadBalancerClient.choose("provider-service-by-http-with-sentinel"); String
		 * url = String.format("http://%s:%s/echo/%s", serviceInstance.getHost(),
		 * serviceInstance.getPort(), appName); System.out.println("request url:" +
		 * url); return restTemplate.getForObject(url, String.class);
		 */
		
		return restTemplate.getForObject(
				"http://provider-service-by-http-with-sentinel/echo/{str}", String.class, appName);
	}
	
	// Block 异常处理函数，参数最后多一个 BlockException，其余与原函数一致.
	public String echoAppNameByRestTemplateBlockHandler(BlockException ex) {
		log.warn("Oops: " + ex.getClass().getCanonicalName());
		return "EchoService.echoAppNameByRestTemplate: 我被限流了";
	}

	// Fallback 函数，函数签名与原函数一致或加一个 Throwable 类型的参数.
	public String echoAppNameByRestTemplateFallback(Throwable ex) {
		log.error("Oops：" + ex.getClass().getCanonicalName());
		return "EchoService.echoAppNameByRestTemplate: 我被降级了";
	}
}
